package cn.lili.modules.grab.haiguan.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.thread.ThreadConfig;
import cn.lili.common.utils.StringUtils;
import cn.lili.modules.goods.client.GoodsSkuClient;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.grab.haiguan.service.IFreeWarehouse;
import cn.lili.modules.member.client.UserClient;
import cn.lili.modules.member.entity.dos.User;
import cn.lili.modules.order.order.entity.constant.FreeWarehouseConstant;
import cn.lili.modules.order.order.entity.dos.Order;
import cn.lili.modules.order.order.entity.dos.OrderItem;
import cn.lili.modules.order.order.entity.vo.warehouse.*;
import cn.lili.modules.order.order.entity.vo.warehouse.customs.*;
import cn.lili.modules.system.client.DictionaryClient;
import cn.lili.modules.system.entity.dos.Dictionary;
import cn.lili.util.AesUtil;
import cn.lili.util.GUIDUtil;
import com.alibaba.fastjson.JSONObject;
import com.api.UserApi;
import com.pojos.Authentication;
import com.pojos.OpenAppUser;
import feign.form.FormData;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 免税仓对接相关接口实现
 */
@Service
@Slf4j
public class FreeWarehouseImpl implements IFreeWarehouse {

    /**
     * 免税仓相关信息注入
     */
    @Value("${freeware.house.url}")
    public String requestUrl;
    @Value("${freeware.house.appKey}")
    public String appKey;
    @Value("${freeware.house.security}")
    public String security;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private GoodsSkuClient goodsSkuClient;
    @Resource
    private UserApi userApi;
    @Resource
    private UserClient userClient;
    @Resource
    private  ThreadConfig threadConfig;
    
    @Resource
    private DictionaryClient dictionaryClient;

    private final static String KEY = "AD42F6697B035B7580E4F6693BE20BAD";
    /**
     * 获取令牌
     *
     * @return 令牌
     */
    private String getToken() {
        String getTokenUrl = requestUrl + FreeWarehouseConstant.GET_TOKEN;
        String token = stringRedisTemplate.boundValueOps("freeware_token").get();
        log.info("redis token == {}", token);
        if (StringUtils.isNotEmpty(token)) {
            return token;
        }
        Map<String, Object> params = new HashMap<>();
        params.put("appKey", appKey);
        params.put("security", security);
        String requestBody = JSONObject.toJSONString(params);
        log.info("requestBody == {}", requestBody);
        //对方测试环境与生产环境传值方式不一样，  生产传from  测试使用body
        Map<String, Object> formData = new HashMap<>();
        formData.put("appKey", appKey);
        formData.put("security", security);
        HttpRequest post1 = HttpUtil.createPost(getTokenUrl).form(formData);
//        HttpRequest post1 = HttpUtil.createPost(getTokenUrl).body(requestBody);
        String body = post1.execute().body();
        log.info("body == {}", body);
        JSONObject jsonObject = JSONObject.parseObject(body);
        if (jsonObject.getInteger("resultCode") != 1) {
            log.error("resultContent == {}", jsonObject.getString("resultContent"));
            throw new ServiceException("token获取失败");
        }
        stringRedisTemplate.boundValueOps("freeware_token").set(jsonObject.getJSONObject("resultData").getString("token"));
        stringRedisTemplate.expire("freeware_token", 30, TimeUnit.MINUTES);
        return jsonObject.getJSONObject("resultData").getString("token");
    }

    /**
     * 发送请求给保税仓
     *
     * @param apiUrl  请求保税仓接口路径
     * @param reqBody 请求数据
     * @return 返回结果
     */
    @Override
    public JSONObject sendHttpRequest(String apiUrl, Object reqBody) {
        log.info("sendHttpRequest2 = {}", JSONObject.toJSONString(reqBody));
        return this.send(requestUrl, apiUrl, reqBody, null);
    }


    /**
     *
     * @param http 域名
     * @param apiUrl api地址
     * @param reqBody 请求数据
     * @param reqType get/post
     * @return 接口请求结果
     */
    public JSONObject send(String http, String apiUrl, Object reqBody, Integer reqType) {
        try {
            String token = this.getToken();
            log.info("token == {}", token);
            String requestBody = JSONObject.toJSONString(reqBody);
            log.info("Request body == {}", requestBody);
            HttpRequest httpRequest = null;
            if (reqType == null) {
                httpRequest = HttpUtil.createPost(http + apiUrl).body(requestBody).header("token", token);
            }
            if (reqType != null) {
                httpRequest = HttpUtil.createGet(http + apiUrl).body(requestBody).header("token", token);
            }
            String responseBody = httpRequest.execute().body();
            log.info("Response body == {}", responseBody);
            return JSONObject.parseObject(responseBody);
        } catch (Exception e) {
            log.error("Error occurred: {}", JSONObject.toJSONString(e.getMessage()));
            e.printStackTrace();
        }
        throw new ServiceException("Failed to send HTTP request");
    }


//    public static void main(String[] args) {
//        String apiUrl = "http://116.153.32.35:80/rpc/eport/upload/CEBMessage";
//        try {
//            String token = "VsILYmmcZg6vtT77FyuIiEmaajTMjLZa9uZJ5sxGLPdMGVln7Z8ehZ6US/HBXQca0mnRKG6ZSglCmnwCWDkIEKWOJAA538UFAM68H0o/pF2VqYLHh0YD/W/aRs76nF2CVoS3nWjhHUYUhxH+LQO7SnVQeTyWpfpe98YeS1TGhdc=";
//            log.info("token == {}", token);
//            String requestBody = "{\"cebMessage\":\"{\\\"order\\\":{\\\"orderHead\\\":{\\\"guid\\\":\\\"HPSS0H-WEASLEY-20240424191659-5PCO0N\\\",\\\"appType\\\":\\\"1\\\",\\\"appTime\\\":\\\"20240424191659\\\",\\\"appStatus\\\":\\\"2\\\",\\\"orderType\\\":\\\"I\\\",\\\"orderNo\\\":\\\"O202404241782951448619266049\\\",\\\"ebpCode\\\":\\\"460168002H\\\",\\\"ebpName\\\":\\\"永利嗨购\\\",\\\"ebcCode\\\":\\\"460168002H\\\",\\\"ebcName\\\":\\\"海南永利国际跨境电子商务有限公司\\\",\\\"goodsValue\\\":\\\"9.9\\\",\\\"freight\\\":\\\"0\\\",\\\"discount\\\":\\\"0\\\",\\\"taxTotal\\\":\\\"0\\\",\\\"acturalPaid\\\":\\\"13.1\\\",\\\"currency\\\":\\\"142\\\",\\\"buyerRegNo\\\":\\\"4\\\",\\\"buyerName\\\":\\\"刘琪友\\\",\\\"buyerTelephone\\\":\\\"17373348393\\\",\\\"buyerIdType\\\":\\\"1\\\",\\\"buyerIdNumber\\\":\\\"430223200101188017\\\",\\\"consignee\\\":\\\"刘琪友\\\",\\\"consigneeTelephone\\\":\\\"17373348393\\\",\\\"consigneeAddress\\\":\\\"海南省,海口市,秀英区,秀英街道-海南温蒂科技有限公司\\\"},\\\"orderList\\\":[{\\\"gnum\\\":1,\\\"itemNo\\\":\\\"1746047068173312002\\\",\\\"itemName\\\":\\\"小湘好香辣火焙鱼农家自制湖南特产零食鱼仔下饭菜下酒菜瓶装 香辣火培鱼（280g）\\\",\\\"gmodel\\\":\\\"香辣火培鱼（280g）\\\",\\\"unit\\\":\\\"011\\\",\\\"qty\\\":\\\"1\\\",\\\"price\\\":\\\"13.1\\\",\\\"totalPrice\\\":\\\"13.1\\\",\\\"currency\\\":\\\"142\\\",\\\"country\\\":\\\"136\\\"}]},\\\"guid\\\":\\\"HPSS0H-WEASLEY-20240424191659-5PCO0N\\\",\\\"version\\\":\\\"1.0\\\",\\\"baseTransfer\\\":{\\\"copCode\\\":\\\"91460000MAD18XKF5P\\\",\\\"copName\\\":\\\"海南永利国际跨境电子商务有限公司\\\",\\\"dxpMode\\\":\\\"DXP\\\",\\\"dxpId\\\":\\\"DXPENT0000630226\\\",\\\"note\\\":\\\"\\\"}}\",\"dataType\":\"JSON\",\"messageType\":\"CEB311Message\"}";
//            log.info("Request body == {}", requestBody);
//            HttpRequest httpRequest = null;
//            httpRequest = HttpUtil.createPost(apiUrl).header("token", token).body(requestBody);
//            String responseBody = httpRequest.execute().body();
//            log.info("Response body == {}", responseBody);
//        } catch (Exception e) {
//            log.error("Error occurred: {}", JSONObject.toJSONString(e.getMessage()));
//            e.printStackTrace();
//        }
//    }

    /**
     * 转运订单创建
     */
    @Override
    public MultiplePackageOrderReq multiplePackageOrder() {
        MultiplePackageOrderReq result = new MultiplePackageOrderReq();
        return result;
    }


    /**
     * 进口订单创建
     */
    @Override
    public ShopSalesOrderReq shopSalesOrderCreate(Order order, List<OrderItem> orderItems) {
        ShopSalesOrderReq result = new ShopSalesOrderReq();
        result.setAmount((int) (order.getFlowPrice() * 100));
        result.setAmountPaid((int) (order.getFlowPrice() * 100));
        result.setFee(0);
        result.setFreight(order.getFreightPrice() != null ? (int) (order.getFreightPrice() * 100) : 0);
        result.setTax(order.getTaxes() != null ? order.getTaxes().multiply(BigDecimal.valueOf(100)).intValue() : 0);
        result.setCouponDiscount(0);
        result.setPrice(order.getGoodsPrice() != null ? (int) (order.getGoodsPrice() * 100) : 0);
        result.setQuantity(order.getGoodsNum());
        result.setSalesOrderNo(order.getOutTradeNo());
        result.setOrderNo(order.getOutTradeNo());
        result.setShopCode("HNYL00001");
        Consignee consignee = new Consignee();
        String[] addressPath = order.getConsigneeAddressPath().split(",");
        consignee.setProvince(StringUtils.isNotEmpty(addressPath[0]) ? addressPath[0] : "");
        consignee.setCity(StringUtils.isNotEmpty(addressPath[1]) ? addressPath[1] : "");
        consignee.setDistrict(StringUtils.isNotEmpty(addressPath[2]) ? addressPath[2] : "");
        consignee.setAddress(order.getConsigneeDetail());
        consignee.setName(order.getConsigneeName());
        consignee.setPhone(order.getConsigneeMobile());
        Buyer buyer = new Buyer();
        buyer.setName(order.getConsigneeName());
        buyer.setPhone(order.getConsigneeMobile());
        User user = userClient.getById(order.getBuyerId());
        OpenAppUser openAppUser = userApi.getUserinfoByOpenId(user.getOpenId());
        Authentication authentication = null;
        if (null != openAppUser) {
            authentication = userApi.authUserInfo(openAppUser.getUId());
            if (authentication == null || StringUtils.isEmpty(authentication.getId())) {
                log.error("未获取到，实名认证信息=={}", JSONObject.toJSONString(openAppUser));
                throw new ServiceException(ResultCode.NAME_OUTH);
            }
        } else {
            throw new ServiceException(ResultCode.NAME_OUTH);
        }
        buyer.setIdentificationNo(order.getBuyerCardNo());
        result.setBuyer(buyer);
        result.setConsignee(consignee);

        List<SalesOrderItems> itemsList = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            GoodsSku goodsSku = goodsSkuClient.getGoodsSkuById(orderItem.getSkuId());
            if (goodsSku == null) {
                log.error("goodsSku 为空 ===  {}" , orderItem.getSkuId());
                continue;
            }
            SalesOrderItems salesOrderItems = new SalesOrderItems();
            salesOrderItems.setItemName(goodsSku.getGoodsName());
            salesOrderItems.setItemCount(orderItem.getNum());
            salesOrderItems.setItemCode(goodsSku.getProductCode());
            salesOrderItems.setHsCode(goodsSku.getThirdPartyPlatformId());
            AtomicInteger counter = new AtomicInteger((int) System.currentTimeMillis());
            int orderItemId = counter.getAndIncrement();
            salesOrderItems.setOrderItemId(orderItemId);
            salesOrderItems.setPrice((int) (orderItem.getGoodsPrice() * 100));
            salesOrderItems.setSubOrderNo(orderItem.getSn());
            salesOrderItems.setWeight((int) Math.round(goodsSku.getWeight()));
            itemsList.add(salesOrderItems);
        }
        result.setSalesOrderItems(itemsList);
        return result;
    }

    /**
     * 出口订单创建
     */
    @Override
    public OrderExCreateReq orderExCreate() {
        OrderExCreateReq result = new OrderExCreateReq();
//        result.set
        return result;
    }

    /**
     * 订单列表查询
     */
    @Override
    public OrderQueryListReq orderQueryList() {
        OrderQueryListReq result = new OrderQueryListReq();

        return result;
    }

    /**
     * 订单拦截
     *
     * @param orderNo       订单号
     * @param interceptType 拦截类型
     * @param remarks       备注
     * @param clientCode    客户编码
     */
    @Override
    public InterceptReq intercept(String orderNo, String remarks, String interceptType, String clientCode) {
        InterceptReq result = new InterceptReq();
        result.setOrderNo(orderNo);
        result.setRemarks(remarks);
        result.setInterceptType(interceptType);
        result.setClientCode(clientCode);
        return result;
    }

    /**
     * 关闭订单拦截
     */
    @Override
    public InterceptReq removeInterception() {
        InterceptReq result = new InterceptReq();

        return result;
    }

    /**
     * 订单配载
     */
    @Override
    public CreateLoadReq createLoad() {
        CreateLoadReq result = new CreateLoadReq();
        return result;
    }

    /**
     * 清单推送
     */
    @Override
    public SendManifestReq sendManifest() {
        SendManifestReq result = new SendManifestReq();

        return result;
    }

    /**
     * 总单/提单 新增( 空总单数据, 无包裹对应关系)
     */
    @Override
    public MawbCreateReq mawbCreate() {
        MawbCreateReq result = new MawbCreateReq();
        return result;
    }

    /**
     * 订单组托/装袋/装箱  ---  订单托盘更新
     */
    @Override
    public OrderPalletUpdateReq orderPalletUpdate() {
        OrderPalletUpdateReq result = new OrderPalletUpdateReq();
        return result;
    }

    /**
     * 打印箱签
     */
    @Override
    public OrderPalletPrintLabelReq orderPalletPrintLabel() {
        OrderPalletPrintLabelReq result = new OrderPalletPrintLabelReq();

        return result;
    }


    /**
     * 快递轨迹更新
     */
    @Override
    public TraceExpressReq traceExpress() {
        TraceExpressReq result = new TraceExpressReq();
        return result;
    }

    /**
     * 更新运单信息
     */
    @Override
    public OrderUpdateNoteReq orderUpdateNote() {
        OrderUpdateNoteReq result = new OrderUpdateNoteReq();

        return result;
    }

    /**
     * 母运单号更新
     */
    @Override
    public OrderWayBillNoReceiveReq orderWayBillNoReceive() {
        OrderWayBillNoReceiveReq result = new OrderWayBillNoReceiveReq();

        return result;
    }

    /**
     * 费用明细评估查询(一票一件)     attributes.multiplePackage = true (一票多件)
     */
    @Override
    public EstimateDetailReq estimateDetail() {
        EstimateDetailReq result = new EstimateDetailReq();

        return result;
    }

    /**
     * 单参数
     *
     * @param key   参数名
     * @param value 参数值
     * @return
     */
    @Override
    public JSONObject generateQueryJson(String key, String value) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(key, value);
        return jsonObject;
    }

    /**
     * 组装海关数据
     *
     * @param order      订单
     * @param orderItems 子订单
     * @return 海关数据
     */
    @Override
    public UploadCEBMessageRequest uploadCEBMessage(Order order, List<OrderItem> orderItems) {
        UploadCEBMessageRequest messageRequest = new UploadCEBMessageRequest();
        messageRequest.setMessageType(MessageType.CEB311Message);
        messageRequest.setDataType(RequestDataType.JSON);

        UploadCEBMessage uploadCEBMessage = new UploadCEBMessage();
        String guid = GUIDUtil.getGuid();
        OrderFree orderFree = new OrderFree();
        OrderHead orderHead = new OrderHead();
        orderHead.setGuid(guid);
        orderHead.setAppType("1");
        orderHead.setAppTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        orderHead.setAppStatus("2");
        orderHead.setOrderType("I");
        orderHead.setOrderNo(order.getOutTradeNo());
        orderHead.setEbpCode("460168002H");
        orderHead.setEbpName("海南永利国际跨境电子商务有限公司");
        orderHead.setEbcCode("460168002H");
        orderHead.setEbcName("海南永利国际跨境电子商务有限公司");
        orderHead.setGoodsValue(order.getGoodsPrice() + "");
        orderHead.setFreight("0");
        orderHead.setDiscount("0");
        orderHead.setTaxTotal("0");
        orderHead.setActuralPaid(order.getFlowPrice() + "");
        orderHead.setCurrency("142");
        orderHead.setBuyerRegNo("4");
        User user = userClient.getById(order.getBuyerId());
        if (user == null) {
            throw new ServiceException("");
        }
        OpenAppUser openAppUser = userApi.getUserinfoByOpenId(user.getOpenId());
        Authentication authentication = null;
        if (null != openAppUser) {
            authentication = userApi.authUserInfo(openAppUser.getUId());
            if (authentication == null || StringUtils.isEmpty(authentication.getId())) {
                log.error("未获取到，实名认证信息=={}", JSONObject.toJSONString(openAppUser));
                throw new ServiceException(ResultCode.NAME_OUTH);
            }
        } else {
            throw new ServiceException(ResultCode.NAME_OUTH);
        }

        orderHead.setBuyerName(AesUtil.decrypt(authentication.getName(), KEY));
        orderHead.setBuyerTelephone(authentication.getMobile());
        orderHead.setBuyerIdType("1");
        orderHead.setBuyerIdNumber(AesUtil.decrypt(authentication.getCardNo(), KEY));
        orderHead.setConsignee(order.getConsigneeName());
        orderHead.setConsigneeTelephone(order.getConsigneeMobile());
        orderHead.setConsigneeAddress(order.getConsigneeAddressPath() +"-"+ order.getConsigneeDetail());
        orderFree.setOrderHead(orderHead);
        List<OrderList> orderListList = new ArrayList<>();

        for (OrderItem orderItem : orderItems) {
            OrderList orderList = new OrderList();
            orderList.setGnum(orderItem.getNum());
            GoodsSku goodsSku = goodsSkuClient.getGoodsSkuById(orderItem.getSkuId());
            orderList.setItemNo(orderItem.getSkuId());
            orderList.setItemName(goodsSku.getGoodsName());
            orderList.setGmodel(goodsSku.getSimpleSpecs());
//            orderList.setItemDescribe("1");
//            orderList.setBarCode("1");
            orderList.setUnit("011");
            orderList.setQty(orderItem.getNum() + "");
            orderList.setPrice(orderItem.getFlowPrice() + "");
            orderList.setTotalPrice(orderItem.getFlowPrice() * orderItem.getNum() + "");
            orderList.setCurrency("142");
            orderList.setCountry("136");
//            orderList.setNote("1");
            orderListList.add(orderList);
        }
        orderFree.setOrderList(orderListList);
        uploadCEBMessage.setOrder(orderFree);
        BaseTransfer baseTransfer = new BaseTransfer();
        baseTransfer.setCopCode("460168002H");
        baseTransfer.setCopName("海南永利国际跨境电子商务有限公司");
        baseTransfer.setDxpMode("DXP");
        baseTransfer.setDxpId("DXPENT0000630226");
        baseTransfer.setNote("");
        uploadCEBMessage.setBaseTransfer(baseTransfer);

        uploadCEBMessage.setVersion("1.0");
        uploadCEBMessage.setGuid(guid);
        uploadCEBMessage.getOrder().getOrderHead().setGuid(guid);
        messageRequest.setCebMessage(uploadCEBMessage);

        return messageRequest;
    }

    /**
     * 发送数据到海关
     *
     * @param reqBody 海关数据
     * @return 海关返回信息
     */
    @Override
    public JSONObject sendCustomsRequest(String apiUrl, Object reqBody) {
        log.info("uploadCEBMessageRequest == {}", JSONObject.toJSONString(reqBody));
        List<Dictionary> sendCustoms = dictionaryClient.getListByCode("send_customs");
        log.info("sendCustoms == {}", JSONObject.toJSONString(sendCustoms));
        if (CollectionUtil.isEmpty(sendCustoms)) {
            log.error("海关无可访问的请求地址,无法上报");
            throw new ServiceException("海关无可访问的请求地址,无法上报");
        }
        String[] split = sendCustoms.stream().map(Dictionary::getValue).collect(Collectors.joining(",")).split(",");
        String randomUrl = null;
        try {
            //当随机选择，时间超过两秒钟就不再继续。选择海关地址了。直接返回没有可用地址
            Callable<String> task = () -> {
                return this.getRandomUrl(split);
            };
            Future<String> submit = Objects.requireNonNull(threadConfig.getAsyncExecutor()).submit(task);
            randomUrl = submit.get(2, TimeUnit.SECONDS);
            log.info("海关的请求地址是：randomUrl == {}", randomUrl);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("sendCustomsRequest ==  ", e);
            throw new ServiceException("海关无可访问的请求地址");
        }
        Integer reqType = null;
        if (apiUrl.equals(FreeWarehouseConstant.RECEIVE_MESSAGE)) {
            reqType = 1;
        }
        return this.send(randomUrl, apiUrl, reqBody, reqType);
    }

    /**
     * 检查域名能否正常访问
     * @param domain 域名
     * @return 是否正常
     */
    public boolean checkDomainAvailability(String domain) {
        try {
            String url = domain + "/rpc/eport/upload/heartbeat";
            log.info("domain == {}", url);
            HttpRequest httpRequest = HttpUtil.createGet(url);
            String responseBody = httpRequest.execute().body();
            log.info("responseBody == {}", responseBody);
            return "true".equals(responseBody);
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("无法连接到域名：" + domain);
        }
        return false;
    }

    /**
     * 1.随机选取，访问地址。
     * 2.测试地址，是否可达。
     *      3.不可达  重新选择地址
     *      4.可达    返回访问地址
     */
    private String getRandomUrl(String[] urls) {
        Random random = new Random();
        int randomIndex = random.nextInt(urls.length);
        String randomUrl = urls[randomIndex];
        log.info("getRandomUrl = {}", randomUrl);
        boolean check = this.checkDomainAvailability(randomUrl);
        if (!check) {
            log.error("地址连接失败，重新选取海关地址 == {}", randomUrl);
            getRandomUrl(urls);
        }
        return randomUrl;
    }
}
